// counter
package web

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"os"
	"path"
	"strings"
	"time"
	"xlog/common"
)

var total int64 = 0

// 合计总字节数
var bodyBytesTotal int64 = 0

// 合计总响应时间
var timeSecondsTotal float64 = 0.0

// 合计响应状态码分布
var statusCodeCounterTotal = common.NewCounter()

//统计Host字节groupby
var bodyBytesHostCounterTotal = common.NewCounterHttp()

//统计Uri字节groupby
var bodyBytesUriCounterTotal = common.NewCounterHttp()

//统计Ip字节groupby
var bodyBytesIpCounterTotal = common.NewCounterHttp()

// 合计Http方法分布
var methodCounterTotal = common.NewCounter()

// 合计host分布
var hostCounterTotal = common.NewCounter()

// 合计协议分布
//var schemeCounterTotal = common.NewCounter()

// 合计响应时间分布
var timeDistCounterTotal = common.NewCounter()

// 合计XFF分布
var xffIPCounterTotal = common.NewCounter()

// 合计RemoteAddress分布
var raIPCounterTotal = common.NewCounter()

// 合计Uri分布
var uriCounterTotal = common.NewCounter()

// 合计Uri模式分布
var uriPtCounterTotal = common.NewCounter()

// 合计RawUri分布
var rawUriCounterTotal = common.NewCounter()
var rawUriCounterFiltered = common.NewCounter()

// 合计UA分布
var uaCounterTotal = common.NewCounter()
var uaCounterFiltered = common.NewCounter()

// 合计referer分布
var rfCounterTotal = common.NewCounter()

var trendCounter = common.NewTrendCounter()

var groupbyCounterTotal = common.NewCounter()

var logf *common.Log

//var ch = make(chan int, 2)

//http模式下后台进行统计
func BackupCounter(logfile string) {
	file, err := os.Open(logfile)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
		//return
	}
	defer file.Close()

	// gzip read
	var bi *bufio.Reader
	if path.Ext(logfile) == ".gz" {
		gfile, err := gzip.NewReader(file)
		if err != nil {
			panic(err)
		}
		defer gfile.Close()
		bi = bufio.NewReader(gfile)
	} else {
		// 建立行式文件缓冲流
		bi = bufio.NewReader(file)
	}

	parser := common.NewLogParser("")
	for {
		//go func() {
		line, err := bi.ReadString('\n')
		if err != nil {
			//break // 读取完成整个文件退出循环
			//fmt.Println("end")
			time.Sleep(30 * time.Second)
			//time.Sleep(500 * time.Millisecond)
		} else {
			total++

			// 使用合适的解析器解析日志
			logf = parser.ParseLog(line)
			if logf == nil {
				continue
			}
			//过滤掉php的post请求
			//if strings.Contains(logf.BackHost, ":111") {
			//	continue
			//}
			var timeDist string

			// 累加总字节数和响应时间
			bodyBytesTotal = bodyBytesTotal + logf.BodyBytes
			timeSecondsTotal = timeSecondsTotal + logf.TimeSeconds

			// 处理总响应状态码分布
			statusCodeCounterTotal.Count(fmt.Sprint(logf.StatusCode))

			// 处理总Http方法分布
			methodCounterTotal.Count(logf.Method)

			// 处理总host分布
			hostCounterTotal.Count(logf.Host)

			// 处理总协议分布
			//schemeCounterTotal.Count(logf.Scheme)

			// 处理总响应时间分布
			timeDist = logf.TimeDist("t")
			timeDistCounterTotal.Count(timeDist)

			// 处理总xff分布
			xffIPCounterTotal.Count(logf.XForwardFor)

			// 处理总remoteaddress分布
			raIPCounterTotal.Count(logf.RemoteAddr)

			// 处理总Uri分布
			uriCounterTotal.Count(logf.Uri)

			// 处理Uri pattern模式分布
			uriPtCounterTotal.Count(logf.UriPattern)

			rawUriCounterTotal.Count(logf.RawUri)

			// 处理总UA分布
			uaCounterTotal.Count(logf.UserAgent)

			// 处理总Referer分布
			rfCounterTotal.Count(logf.Referer)

			//统计trend
			trendCounter.CountHttp(logf, "m")

			//统计Host字节groupby
			bodyBytesHostCounterTotal.CountHttpBytes(logf, logf.Host)

			//统计Uri字节groupby
			bodyBytesUriCounterTotal.CountHttpBytes(logf, logf.RawUri)

			//统计Ip字节groupby
			bodyBytesIpCounterTotal.CountHttpBytes(logf, logf.RemoteAddr)

			//记录地区响应时间到map
			common.CountChinaMap(logf.XRealIP, logf.TimeSeconds, logf.StatusCode)

			if common.MatchFilters(FilterCount("s != 200 && s != 301 && s != 302"), logf, tjf) {
				rawUriCounterFiltered.Count(logf.RawUri)
				uaCounterFiltered.Count(logf.UserAgent)
			}
		}
		//ch <- 1
		//}()
		//<-ch
	}
}

//为|| 时为true
var tjf bool

func FilterCount(filter string) []*common.Filter {
	// 初始化过滤条件并显示提示
	var filters []*common.Filter
	filters = make([]*common.Filter, 0)
	var fx []string
	if filter != "" {
		if strings.Contains(filter, "||") {
			tjf = true
			fx = strings.Split(filter, " || ")
		} else {
			fx = strings.Split(filter, " && ")
		}
	}
	for _, fy := range fx {
		f := common.NewFilter(fy)
		filters = append(filters, f)
	}
	return filters
}
